{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# 5. Pandas 入门 Getting Started with Pandas\n",
    "\n",
    "+ 数据对齐\n",
    "+ 时间序列\n",
    "+ 处理缺失数据\n",
    "\n",
    "作者在本书中的习惯是将 `Series` 与 `DataFrame` 导入到本地命名空间，即：`from pandas import Series, Dataframe`，因为使用次数比较多。\n",
    "\n",
    "在 5.1 节我们仍然采用之前学习 NumPy 的方式，即使用 `numpy.array()` 的方式，以便让大家更深刻地理解这些名称的层级关系。\n",
    "\n",
    "不过需要注意的是，`numpy.array()` 是函数，而 `pandas.Series()` 与 `pandas.DataFrame()` 均为类，虽然形式上与使用时并无较大的差异，并且 `numpy.array()` 返回的依然是对象，但还是建议大家头脑清醒地区分二者。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 5.1 Pandas 数据结构的介绍 Introduction to pandas Data Structures\n",
    "\n",
    "两个主要的数据结构：Series 和 DataFrame"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "source": [
    "# 模块导入\r\n",
    "import os, sys\r\n",
    "sys.path.append(os.path.dirname(os.getcwd()))\r\n",
    "import numpy\r\n",
    "import pandas\r\n",
    "from dependency import arr_info"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.1.1 Series数据结构\n",
    "\n",
    "A Series is a one-dimensional array-like object containing an array of data (of any NumPy data type) and an associated array of data labels, called its index.\n",
    "\n",
    "创建Series：`ser_object = pandas.Series(data, index=)`\n",
    "\n",
    "如果不指定索引，将会自动生成 0 ~ (N-1) 的整数索引；如果指定了索引，可以用指定的索引访问元素\n",
    "\n",
    "可以对Series进行数组运算（类似Numpy中对数组的运算，例如布尔索引、标量与数组的四则运算、调用Numpy函数等），将保留索引与值之间的连接（index-value link）；\n",
    "\n",
    "可以将 Series 看作定长有序的字典，因为它是索引值到数据的一个映射（mapping of index values to data values）；\n",
    "\n",
    "部分重要属性：\n",
    "\n",
    "+ `series.index`\n",
    "+ `series.values`\n",
    "+ `name` 属性：\n",
    "    + `series.name`\n",
    "    + `series.index.name`\n",
    "\n",
    "检测数据是否缺失：\n",
    "\n",
    "+ `pandas.isnull(series)`\n",
    "+ `pandas.notnull(series)`\n",
    "\n",
    "或其对应的类方法：\n",
    "\n",
    "+ `series.isnull()`\n",
    "+ `series.notnull()`"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "source": [
    "# 创建Series\n",
    "\n",
    "ser1_1 = pandas.Series([7, 7, 1, 0])\n",
    "\n",
    "arr_info([ ser1_1 ])\n",
    "arr_info([ ser1_1[3] ])       # 访问单个元素的方式与列表、NumPy数组相同。注意：Series是一维数组\n",
    "arr_info([ ser1_1.values ])   # 用 Series 的 values 属性获取数组\n",
    "arr_info([ ser1_1.index ])    # 用 Series 的 index 属性获取索引"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[0    7\n",
      "1    7\n",
      "2    1\n",
      "3    0\n",
      "dtype: int64]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[0]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[array([7, 7, 1, 0], dtype=int64)]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[RangeIndex(start=0, stop=4, step=1)]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "source": [
    "# 创建带有自定义标签（索引）的Series\n",
    "\n",
    "ser1_2 = pandas.Series( [5, 2, 0, 1], index=[\"wo\", \"ai\", \"ni\", \"ya\"] )\n",
    "\n",
    "arr_info([ ser1_2 ])\n",
    "arr_info([ ser1_2[0] ])       # 仍然可以用数字索引访问\n",
    "arr_info([ ser1_2[\"wo\"] ])    # 也可以用指定的标签访问\n",
    "arr_info([ ser1_2[ [\"wo\", \"ai\", \"ni\"] ] ])  # 可以用花式索引访问多个元素（注意传入的是一个列表）"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[wo    5\n",
      "ai    2\n",
      "ni    0\n",
      "ya    1\n",
      "dtype: int64]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[5]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[5]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[wo    5\n",
      "ai    2\n",
      "ni    0\n",
      "dtype: int64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "source": [
    "# 依然可以使用NumPy的数组操作、函数\n",
    "\n",
    "arr_info([ ser1_2[ser1_2 > 1] ])    # 布尔索引\n",
    "arr_info([ ser1_2 * 2 ])            # 数组与标量的运算\n",
    "arr_info([ numpy.exp(ser1_2 * 2) ]) # NumPy函数"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[wo    5\n",
      "ai    2\n",
      "dtype: int64]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[wo    10\n",
      "ai     4\n",
      "ni     0\n",
      "ya     2\n",
      "dtype: int64]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[wo    22026.465795\n",
      "ai       54.598150\n",
      "ni        1.000000\n",
      "ya        7.389056\n",
      "dtype: float64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "source": [
    "# 可以将Series看作定长有序的字典\n",
    "\n",
    "print(\"ni\" in ser1_2)\n",
    "print(\"ta\" in ser1_2)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "True\n",
      "False\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "source": [
    "# 通过字典来创建Series\n",
    "\n",
    "data1_1 = { \"shirt\": 180, \"pants\": 200, \"coat\": 1000, \"hat\": 50 }\n",
    "\n",
    "ser1_3 = pandas.Series(data1_1)\n",
    "\n",
    "arr_info([ ser1_3 ])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[shirt     180\n",
      "pants     200\n",
      "coat     1000\n",
      "hat        50\n",
      "dtype: int64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "source": [
    "# 指定其他标签（索引）\n",
    "\n",
    "states = [ \"umbrella\", \"shirt\", \"pants\",\"umbrella\", \"coat\", \"hat\" ]\n",
    "\n",
    "ser1_4 = pandas.Series(data1_1, index=states)\n",
    "\n",
    "arr_info([ ser1_4 ])\n",
    "\n",
    "# 注：重复标签并不会被删去"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[umbrella       NaN\n",
      "shirt        180.0\n",
      "pants        200.0\n",
      "umbrella       NaN\n",
      "coat        1000.0\n",
      "hat           50.0\n",
      "dtype: float64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "source": [
    "# 检测缺失数据：isnull()、notnull()\n",
    "\n",
    "arr_info([ pandas.isnull(ser1_4) ])\n",
    "# ser1_4.isnull()    # 或相应的类方法\n",
    "\n",
    "arr_info([ pandas.notnull(ser1_4) ])\n",
    "# ser1_4.notnull()    # 或相应的类方法"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[umbrella     True\n",
      "shirt       False\n",
      "pants       False\n",
      "umbrella     True\n",
      "coat        False\n",
      "hat         False\n",
      "dtype: bool]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[umbrella    False\n",
      "shirt        True\n",
      "pants        True\n",
      "umbrella    False\n",
      "coat         True\n",
      "hat          True\n",
      "dtype: bool]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "source": [
    "# 数据对齐（Data alignment），详细内容将在以后的章节讲解\n",
    "\n",
    "price_added = ser1_3 + ser1_4       # pandas会自动对齐相同标签的数据再进行运算\n",
    "\n",
    "arr_info([ ser1_3, ser1_4, price_added ])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[shirt     180\n",
      "pants     200\n",
      "coat     1000\n",
      "hat        50\n",
      "dtype: int64, umbrella       NaN\n",
      "shirt        180.0\n",
      "pants        200.0\n",
      "umbrella       NaN\n",
      "coat        1000.0\n",
      "hat           50.0\n",
      "dtype: float64, coat        2000.0\n",
      "hat          100.0\n",
      "pants        400.0\n",
      "shirt        360.0\n",
      "umbrella       NaN\n",
      "umbrella       NaN\n",
      "dtype: float64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "source": [
    "# name属性\n",
    "\n",
    "ser1_3.name = \"Price List\"\n",
    "ser1_3.index.name = \"Clothes\"\n",
    "arr_info([ ser1_3 ])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[Clothes\n",
      "shirt     180\n",
      "pants     200\n",
      "coat     1000\n",
      "hat        50\n",
      "Name: Price List, dtype: int64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "source": [
    "# 修改索引：对index属性赋值即可\n",
    "\n",
    "arr_info([ ser1_1 ])\n",
    "\n",
    "ser1_1.index = [ \"C\", \"o\", \"d\", \"e\" ]\n",
    "arr_info([ ser1_1 ])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[0    7\n",
      "1    7\n",
      "2    1\n",
      "3    0\n",
      "dtype: int64]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[C    7\n",
      "o    7\n",
      "d    1\n",
      "e    0\n",
      "dtype: int64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.1.2 DataFrame数据结构\n",
    "\n",
    "A DataFrame represents a tabular, spreadsheet-like data structure containing an ordered collection of columns, each of which can be a different value type (numeric, string, boolean, etc.).\n",
    "\n",
    "创建DataFrame：`df_object = pandas.DataFrame(data, columns=)`，传入的数据需为等长度的列表、Numpy数组等构成的字典（也可以直接传入列表、数组等，但生成的DataFrame将只有整数索引）；\n",
    "\n",
    "引用：\n",
    "+ 引用一列：`df_object[\"column_str\"]` 或 `df_object.column_str`；\n",
    "+ 引用元素：`df_object[\"column_str\"][index]` 或 `df_object.column_str[index]`；\n",
    "\n",
    "`df_object.cloumns`：类属性，可以查看列标签\n",
    "\n",
    "`del df_object[\"string_index\"]`：删除某列\n",
    "\n",
    "部分重要属性：\n",
    "\n",
    "+ `dataframe.index`：行标签（索引）\n",
    "+ `dataframe.columns`：列标签（索引）\n",
    "+ `dataframe.values`：包含所有数据的NumPy数组\n",
    "+ `name` 属性：\n",
    "    + `dataframe.name`\n",
    "    + `dataframe.index.name`\n",
    "    + `dataframe.columns.name`"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "source": [
    "# 创建DataFrame\r\n",
    "\r\n",
    "# 利用字典\r\n",
    "data2_1 = { \"Nation\": [\"BR\", \"UK\", \"CN\", \"GR\"], \r\n",
    "            \"City\": [\"Rio\", \"London\", \"Beijing\", \"Athens\"], \r\n",
    "            \"Year\": [2016, 2012, 2008, 2004] \r\n",
    "            }\r\n",
    "\r\n",
    "frame2_1 = pandas.DataFrame(data2_1)\r\n",
    "\r\n",
    "# 利用Series\r\n",
    "ser2_1 = pandas.Series([200,300,400], name=\"Wavelength\")\r\n",
    "ser2_2 = pandas.Series([123,900,231], name=\"Intensity\")\r\n",
    "data2_2 = {\"wavelength\": ser2_1, \"intensity\": ser2_2}\r\n",
    "\r\n",
    "frame2_2 = pandas.DataFrame(data2_2)\r\n",
    "\r\n",
    "arr_info(frame2_1, frame2_2)\r\n",
    "frame2_1  # Jupyter Notebook 会优化显示为表格的形式"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'pandas.core.frame.DataFrame'>\n",
      "  Nation     City  Year\n",
      "0     BR      Rio  2016\n",
      "1     UK   London  2012\n",
      "2     CN  Beijing  2008\n",
      "3     GR   Athens  2004\n",
      "【2】\n",
      " 类 型: <class 'pandas.core.frame.DataFrame'>\n",
      "   wavelength  intensity\n",
      "0         200        123\n",
      "1         300        900\n",
      "2         400        231\n"
     ]
    },
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "  Nation     City  Year\n",
       "0     BR      Rio  2016\n",
       "1     UK   London  2012\n",
       "2     CN  Beijing  2008\n",
       "3     GR   Athens  2004"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Nation</th>\n",
       "      <th>City</th>\n",
       "      <th>Year</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>BR</td>\n",
       "      <td>Rio</td>\n",
       "      <td>2016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>UK</td>\n",
       "      <td>London</td>\n",
       "      <td>2012</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>CN</td>\n",
       "      <td>Beijing</td>\n",
       "      <td>2008</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>GR</td>\n",
       "      <td>Athens</td>\n",
       "      <td>2004</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "execution_count": 27
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "source": [
    "# 指定列标签的顺序\r\n",
    "\r\n",
    "frame2_3 = pandas.DataFrame(frame2_1, columns=[\"Year\", \"Nation\", \"City\"])        # 指定列的顺序\r\n",
    "arr_info([ frame2_1, frame2_3 ])\r\n",
    "\r\n",
    "frame2_3 = pandas.DataFrame(frame2_1, columns=[\"Year\", \"Nation\", \"City\", \"th\"])  # 指定列如果不存在数据将变为NaN\r\n",
    "arr_info([ frame2_1, frame2_3 ])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[  Nation     City  Year\n",
      "0     BR      Rio  2016\n",
      "1     UK   London  2012\n",
      "2     CN  Beijing  2008\n",
      "3     GR   Athens  2004,    Year Nation     City\n",
      "0  2016     BR      Rio\n",
      "1  2012     UK   London\n",
      "2  2008     CN  Beijing\n",
      "3  2004     GR   Athens]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[  Nation     City  Year\n",
      "0     BR      Rio  2016\n",
      "1     UK   London  2012\n",
      "2     CN  Beijing  2008\n",
      "3     GR   Athens  2004,    Year Nation     City  th\n",
      "0  2016     BR      Rio NaN\n",
      "1  2012     UK   London NaN\n",
      "2  2008     CN  Beijing NaN\n",
      "3  2004     GR   Athens NaN]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "source": [
    "# 将DataFrame的一列获取为一个Series\r\n",
    "\r\n",
    "arr_info([ frame2_3[\"City\"] ])\r\n",
    "arr_info([ frame2_3.Year ])\r\n",
    "# arr_info([ frame2_3.ix[3] ])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[0        Rio\n",
      "1     London\n",
      "2    Beijing\n",
      "3     Athens\n",
      "Name: City, dtype: object]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[0    2016\n",
      "1    2012\n",
      "2    2008\n",
      "3    2004\n",
      "Name: Year, dtype: int64]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "source": [
    "# 赋值\r\n",
    "\r\n",
    "frame2_3[\"th\"] = 0                   # 赋值为一样的标量\r\n",
    "frame2_3[\"th\"] = [31, 30, 29, 28]    # 赋值为不同的值\r\n",
    "frame2_3[\"th\"] = pandas.Series( [30, 29, 28], index=[1, 2, 3], dtype=\"int32\" ) # 利用Series赋值。严格对应index，不存在的赋值为NaN\r\n",
    "frame2_3[\"th\"] = numpy.flipud(numpy.arange(28, 32))  # 利用 ndarray赋值。numpy.flipud()为倒序功能\r\n",
    "\r\n",
    "frame2_3"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "   Year Nation     City  th\n",
       "0  2016     BR      Rio  31\n",
       "1  2012     UK   London  30\n",
       "2  2008     CN  Beijing  29\n",
       "3  2004     GR   Athens  28"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Year</th>\n",
       "      <th>Nation</th>\n",
       "      <th>City</th>\n",
       "      <th>th</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2016</td>\n",
       "      <td>BR</td>\n",
       "      <td>Rio</td>\n",
       "      <td>31</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2012</td>\n",
       "      <td>UK</td>\n",
       "      <td>London</td>\n",
       "      <td>30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2008</td>\n",
       "      <td>CN</td>\n",
       "      <td>Beijing</td>\n",
       "      <td>29</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2004</td>\n",
       "      <td>GR</td>\n",
       "      <td>Athens</td>\n",
       "      <td>28</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "execution_count": 15
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "source": [
    "# 删除列\r\n",
    "\r\n",
    "print(frame2_3.columns)\r\n",
    "\r\n",
    "# 不存在的列将被自动创建\r\n",
    "frame2_3[\"Month\"] = [0, 0, 0, 0]\r\n",
    "print(frame2_3.columns)\r\n",
    "print(frame2_3)\r\n",
    "\r\n",
    "# 删除指定的列\r\n",
    "del frame2_3[\"Month\"]\r\n",
    "print(frame2_3.columns)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Index(['Year', 'Nation', 'City', 'th'], dtype='object')\n",
      "Index(['Year', 'Nation', 'City', 'th', 'Month'], dtype='object')\n",
      "   Year Nation     City  th  Month\n",
      "0  2016     BR      Rio  31      0\n",
      "1  2012     UK   London  30      0\n",
      "2  2008     CN  Beijing  29      0\n",
      "3  2004     GR   Athens  28      0\n",
      "Index(['Year', 'Nation', 'City', 'th'], dtype='object')\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "source": [
    "# 嵌套字典：外层键作为列索引，内层键作为行索引\r\n",
    "\r\n",
    "data2_4 = { \"Nevada\": {2001: 2.4, 2002: 2.9}, \r\n",
    "            \"Ohio\": {2000: 1.5, 2001: 1.7, 2002: 3.6} \r\n",
    "            }\r\n",
    "\r\n",
    "frame2_4 = pandas.DataFrame(data2_4)\r\n",
    "arr_info([ frame2_4, frame2_4.T ])  # DataFrame可以转置\r\n",
    "\r\n",
    "# frame2_4 = pandas.DataFrame(data2_4, index=[2000, 2001, 2002, 2003])    # 内层字典的键会被合并，可以显式指定索引\r\n",
    "arr_info([ frame2_4, frame2_4.T ])  # DataFrame可以转置"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[      Nevada  Ohio\n",
      "2001     2.4   1.7\n",
      "2002     2.9   3.6\n",
      "2000     NaN   1.5,         2001  2002  2000\n",
      "Nevada   2.4   2.9   NaN\n",
      "Ohio     1.7   3.6   1.5]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[      Nevada  Ohio\n",
      "2001     2.4   1.7\n",
      "2002     2.9   3.6\n",
      "2000     NaN   1.5,         2001  2002  2000\n",
      "Nevada   2.4   2.9   NaN\n",
      "Ohio     1.7   3.6   1.5]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "source": [
    "# 由Series组成的字典\r\n",
    "\r\n",
    "data2_5 = {\"Ohio\": frame2_4[\"Ohio\"][:-1], \"Nevada\": frame2_4[\"Nevada\"][:2]}\r\n",
    "\r\n",
    "frame2_5 = pandas.DataFrame(data2_5)\r\n",
    "frame2_5"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "      Ohio  Nevada\n",
       "2001   1.7     2.4\n",
       "2002   3.6     2.9"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Ohio</th>\n",
       "      <th>Nevada</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2001</th>\n",
       "      <td>1.7</td>\n",
       "      <td>2.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2002</th>\n",
       "      <td>3.6</td>\n",
       "      <td>2.9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "execution_count": 18
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "source": [
    "# 其他类型的数据\r\n",
    "\r\n",
    "data2_5 = numpy.arange(1, 13).reshape(3, 4)\r\n",
    "\r\n",
    "frame2_5 = pandas.DataFrame(data2_5)\r\n",
    "\r\n",
    "frame2_5"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "   0   1   2   3\n",
       "0  1   2   3   4\n",
       "1  5   6   7   8\n",
       "2  9  10  11  12"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>6</td>\n",
       "      <td>7</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>9</td>\n",
       "      <td>10</td>\n",
       "      <td>11</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "execution_count": 19
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "source": [
    "# index、column与frame的name属性\r\n",
    "\r\n",
    "frame2_3.name = \"Olympic Games\"\r\n",
    "frame2_3.index.name = \"NO.\"\r\n",
    "frame2_3.columns.name = \"Info.\"\r\n",
    "\r\n",
    "print(frame2_3.name)\r\n",
    "print(frame2_3.index.name)\r\n",
    "print(frame2_3.columns.name)\r\n",
    "frame2_3"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Olympic Games\n",
      "NO.\n",
      "Info.\n"
     ]
    },
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "Info.  Year Nation     City  th\n",
       "NO.                            \n",
       "0      2016     BR      Rio  31\n",
       "1      2012     UK   London  30\n",
       "2      2008     CN  Beijing  29\n",
       "3      2004     GR   Athens  28"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>Info.</th>\n",
       "      <th>Year</th>\n",
       "      <th>Nation</th>\n",
       "      <th>City</th>\n",
       "      <th>th</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>NO.</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2016</td>\n",
       "      <td>BR</td>\n",
       "      <td>Rio</td>\n",
       "      <td>31</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2012</td>\n",
       "      <td>UK</td>\n",
       "      <td>London</td>\n",
       "      <td>30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2008</td>\n",
       "      <td>CN</td>\n",
       "      <td>Beijing</td>\n",
       "      <td>29</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2004</td>\n",
       "      <td>GR</td>\n",
       "      <td>Athens</td>\n",
       "      <td>28</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "execution_count": 20
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "source": [
    "# index、columns、value属性\r\n",
    "\r\n",
    "arr_info([ frame2_3.index ])\r\n",
    "arr_info([ frame2_3.columns ])\r\n",
    "arr_info([ frame2_3.values ])   # 如果数据类型不同，则dtype将会选用能兼容所有列的数据类型"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[RangeIndex(start=0, stop=4, step=1, name='NO.')]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[Index(['Year', 'Nation', 'City', 'th'], dtype='object', name='Info.')]\n",
      "【1】\n",
      " 类 型: <class 'list'>\n",
      "[array([[2016, 'BR', 'Rio', 31],\n",
      "       [2012, 'UK', 'London', 30],\n",
      "       [2008, 'CN', 'Beijing', 29],\n",
      "       [2004, 'GR', 'Athens', 28]], dtype=object)]\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 5.1.3 索引对象 Index Objects\n",
    "\n",
    "pandas的Index对象主要负责：\n",
    "\n",
    "+ 轴标签（axis labels）\n",
    "+ 元数据（metadata）：轴名称（axis name）、名称（names）\n",
    "\n",
    "Index对象是不可修改的（immutable），这样可以使Index对象在多个数据结构间安全共享；\n",
    "\n",
    "pandas中主要的几种Index对象：\n",
    "\n",
    "+ `Index`：将轴标签表示为一个由Python对象组成的NumPy数组；\n",
    "+ `Int64Index`：针对整数的特殊Index；\n",
    "+ `MultiIndex`：“层次化（Hierarchical）”索引对象，表示单个轴上的多层索引；\n",
    "+ `DatetimeIndex`：存储纳秒级的时间戳（timestamps），使用NumPy的datetime64类型表示；\n",
    "+ `PeriodIndex`：针对时间间隔数据（Period data/timespans）的特殊Index；\n",
    "\n",
    "Index对象的方法和属性：\n",
    "\n",
    "+ `index.append()`：连接另一个Index对象，产生一个新的Index；\n",
    "+ `index.diff()`：计算差集；\n",
    "+ `index.intersection()`：计算交集\n",
    "+ `index.union()`：计算并集\n",
    "+ `index.isin()`：返回布尔数组，表示是否包含传入集合中的元素；\n",
    "+ `index.delete()`：删除索引 `i` 处的元素，并得到新的Index；\n",
    "+ `index.drop()`： 删除传入的值，并得到新的Index；\n",
    "+ `index.insert()`：将元素插入索引 `i` 处，并得到新的Index；\n",
    "+ `index.is_monotonic()`：当各元素大于等于前一个元素时，返回True；\n",
    "+ `index.is_unique()`：当Index没有重复值时，返回True；\n",
    "+ `index.unique()`：返回Index唯一化的数组；"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "source": [
    "# index对象\n",
    "\n",
    "ser3_1 = pandas.Series(range(3), index=[\"a\", \"b\", \"c\"])\n",
    "\n",
    "index_obj_1 = ser3_1.index\n",
    "\n",
    "print(index_obj_1)\n",
    "print(index_obj_1[0])\n",
    "print(index_obj_1[1:])    # 由于索引本身也是数组，所以可以对其进行切片操作"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Index(['a', 'b', 'c'], dtype='object')\n",
      "a\n",
      "Index(['b', 'c'], dtype='object')\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "source": [
    "# index对象不可修改（immutable）\n",
    "\n",
    "# index_obj_1[1] = \"A\"    # 错误！\n",
    "print(index_obj_1)\n",
    "\n",
    "# Immutability is important so that Index objects can be safely shared among data structures:\n",
    "index_obj_2 = pandas.Index(range(3))\n",
    "ser3_2 = pandas.Series([5.56, 5.8, 7.62], index=index_obj_2)\n",
    "\n",
    "print(ser3_2)\n",
    "print(ser3_2.index is index_obj_2)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Index(['a', 'b', 'c'], dtype='object')\n",
      "0    5.56\n",
      "1    5.80\n",
      "2    7.62\n",
      "dtype: float64\n",
      "True\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "source": [
    "# Index的功能类似于一个固定大小的集合（set）\n",
    "\n",
    "print(frame2_3)\n",
    "\n",
    "print(\"2020\" in frame2_3.index)\n",
    "\n",
    "print(\"City\" in frame2_3.columns)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Info.  Year Nation     City  th\n",
      "NO.                            \n",
      "0      2016     BR      Rio  31\n",
      "1      2012     UK   London  30\n",
      "2      2008     CN  Beijing  29\n",
      "3      2004     GR   Athens  28\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "source": [
    "# Index的类方法\n",
    "\n",
    "index_obj_3 = pandas.Index([\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"])\n",
    "print(index_obj_3)\n",
    "\n",
    "index_obj_3 = index_obj_3.delete(1)   # 注意这里传入的是Index数组的index=1，指向第二个元素\n",
    "print(index_obj_3)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], dtype='object')\n",
      "Index(['a', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], dtype='object')\n"
     ]
    }
   ],
   "metadata": {}
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "2df30c634058628fc5df5036be3dee25b811a252316c0aa1ff7f50eb8aecb5be"
  },
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.9.6 64-bit ('venv': venv)"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}